package cn.t.server;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import cn.t.base.TServer;

// https://blog.csdn.net/a78270528/article/details/80318571
/**
 * SocketServer
 * 
 * @author TMQ
 */
public class TMQServer implements TServer {

  private final static Map<Long, TMQServer> THREAD_MAP = new HashMap<>();

  private Integer port;

  private ServerSocket server;
  
  private boolean status;

  /**
   * @param args
   * @throws IOException
   */
  public static void main(String[] args) {
    TMQServer server = new TMQServer();
    
    Thread t = new Thread(() -> {
      server.initServer();
    });
    THREAD_MAP.put(t.getId(), server);
    t.start();
    
    Scanner sc = new Scanner(System.in);
    
    while(true) {
      String line = sc.nextLine();
      if ("quit".equals(line)) {
        THREAD_MAP.entrySet().forEach(entry -> {
          entry.getValue().shutDown();
          System.out.println("线程ID为: " + entry.getKey() + "的服务器关闭...");
        });
        sc.close();
        break;
      } else if ("server-list".equals(line)) {
        showTasks();
        System.out.println("输入线程ID以关闭对应的服务器,输入'quit'以关闭所有服务器并且退出程序: ");
      } else if ("help".equals(line)) {
        System.out.println("\033[36;4m" + "退出: quit" + "\033[0m");
        System.out.println("\033[36;4m" + "服务器列表: server-list" + "\033[0m");
      } else {
        try {
          if (THREAD_MAP.get(Long.parseLong(line)) != null) {
            THREAD_MAP.get(Long.parseLong(line)).shutDown();
            System.out.println("线程ID为: " + line + "的服务器关闭...");
            THREAD_MAP.remove(Long.parseLong(line));
          } else {
            System.out.println("没有对应ID的服务器.");
          }
        } catch (Exception e) {
          System.out.println("请输入正确的服务器ID或者指令(输入help获取帮助)");
        }
      }
    }
  }
  
  @Override
  public int initServer() {
    
    if (this.port == null) {
      this.port = DEFAULT_PORT;
    }
    // 使用线程池，防止并发过高时创建过多线程耗尽资源
    ExecutorService threadPool = Executors.newFixedThreadPool(100);
    try {
      this.server = new ServerSocket(this.port);
      // 设置循环状态
      this.status = true;
      // 循环等待
      while (this.status) {
        // 获取套接字
        Socket socket = this.server.accept();
        // 一次请求开启一个线程处理
        Runnable task = () -> {
          System.out.println("-------线程【" + Thread.currentThread().getName() + "】开始执行-------");
          try (InputStream inputStream = socket.getInputStream();) {
            byte[] bytes = new byte[1024];
            int len;
            StringBuilder sb = new StringBuilder();
            while ((len = inputStream.read(bytes)) != -1) {
              sb.append(new String(bytes, 0, len, "UTF-8"));
            }
            System.out.println("--------START GET MESSAGE FROM CLIENT-------->");
            System.out.println(sb);
            System.out.println("<--------END GET MESSAGE FROM CLIENT--------");

            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("服务器传输完成".getBytes("UTF-8"));

          } catch (Exception e) {
            e.printStackTrace();
          }
        };
        if (threadPool.submit(task, true).get()) {
          socket.close();
          System.out.println("服务器ID： " + Thread.currentThread().getId() + "服务器名: " + Thread.currentThread().getName() + " 通信完成");
        }
      }
    } catch (SocketException e) {
	e.printStackTrace();
      try {
        System.out.println("2秒后开始关闭..等待任务完成.");
        threadPool.awaitTermination(2000, TimeUnit.MILLISECONDS);
        threadPool.shutdown();
      } catch (InterruptedException e1) {
        e1.printStackTrace();
      }
    } catch (Exception e) {
      // 端口占用等
      e.printStackTrace();
      return -1;
    } finally {
      if (this.server != null) {
        try {
          this.server.close();
        } catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
    return 0;
  }

  @Override
  public void shutDown() {
    this.status = false;
    try {
      this.server.close();
    } catch (IOException e) {
      e.printStackTrace();
    }
  }
  
  private static void showTasks() {
    System.out.println("\033[30;4m" + "当前运行中的服务器实例:" + "\033[0m");
    ThreadGroup currentGroup = Thread.currentThread().getThreadGroup();
    int threadsNum = currentGroup.activeCount();
    Thread[] lstThreads = new Thread[threadsNum];
    currentGroup.enumerate(lstThreads);
    for (int i = 0; i < threadsNum; i++) {
      if (lstThreads[i].getName().startsWith("pool")) {
        continue;
      }
      System.out.println("线程名: " + lstThreads[i].getName() + " ,线程ID: " + lstThreads[i].getId());
   }
  }
}
